#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import subprocess
import json
import time
import uuid
import rospy
import hashlib
import os.path
import socket
from std_msgs.msg import String

from vlc.srv import Play

__author__ = "yujikang (aoxun)"
__version__ = "0.0.1"
__license__ = "BSD"

try:  # attempt to use the Python 2 modules
    from urllib import urlencode
    from urllib2 import Request, urlopen, URLError, HTTPError
except ImportError:  # use the Python 3 modules
    from urllib.parse import urlencode
    from urllib.request import Request, urlopen
    from urllib.error import URLError, HTTPError

class RequestError(Exception): pass
class NoAudio(Exception): pass
class RecognitionError(Exception): pass

def play_mp3(path):
    subprocess.Popen(['mpg321', '-q', path]).wait()


class ChatController(object):
    def __init__(self, baidu_id, baidu_secret, tts_timeout):
        self._baidu_id = baidu_id
        self._baidu_secret = baidu_secret
        self._timeout = tts_timeout
        self._time = rospy.Duration(0)
        self._running = False

        rospy.Subscriber("/text_to_speech", String, self.text_to_speech)

    def text_to_speech(self, data):
        # if self._running:
        #     return
        self.update_token()
        url = "http://tsn.baidu.com/text2audio?{}".format(urlencode({
            "tex": data.data,
            "lan": 'zh',
            "tok": self.baidu_cached_access_token,
            "ctp": 1,
            "cuid": uuid.uuid4(),
            "spd": 5,
            "pit": 5,
            "vol": 5,
            "per": 4,
        }))
        request = Request(url, headers={})
        try:
            tts_time = time.time()
            response = urlopen(request, timeout=self.tts_timeout)
            print("tts_time = %f" % (time.time() - tts_time))
            # print response.headers
            ofp = open('tts.mp3', "wb")
            ofp.write(response.read())
            ofp.close()
            # self.play_service("talk.3gp")
            play_mp3('tts.mp3')
            # self.play_service("look.3gp")
        except HTTPError as e:
            # play_mp3('shuaige.mp3')
            print("tts request failed: {}".format(e.reason))
            # raise RequestError("recognition request failed: {}".format(e.reason))
        except URLError as e:
            # play_mp3('shuaige.mp3')
            print("tts connection failed: {}".format(e.reason))
            # raise RequestError("recognition connection failed: {}".format(e.reason))
        except socket.error as e:
            # play_mp3('shuaige.mp3')
            print("tts connection failed: {}".format(e))
            pass

    def update_token(self):
        access_token, expire_time = getattr(self, "baidu_cached_access_token", None), getattr(self, "baidu_cached_access_token_expiry", None)
        allow_caching = True
        try:
            from time import monotonic  # we need monotonic time to avoid being affected by system clock changes, but this is only available in Python 3.3+
        except ImportError:
            try:
                from monotonic import monotonic  # use time.monotonic backport for Python 2 if available (from https://pypi.python.org/pypi/monotonic)
            except (ImportError, RuntimeError):
                expire_time = None  # monotonic time not available, don't cache access tokens
                allow_caching = False  # don't allow caching, since monotonic time isn't available
        if expire_time is None or monotonic() > expire_time:  # caching not enabled, first credential request, or the access token from the previous one expired
            # get an access token using OAuth
            credential_url = "https://openapi.baidu.com/oauth/2.0/token?{}".format(urlencode({
                "grant_type": "client_credentials",
                "client_id": self._baidu_id,
                "client_secret": self._baidu_secret,
            }))
            credential_request = Request(credential_url, data=b"", headers={})

            if allow_caching:
                start_time = monotonic()
            try:
                credential_response = urlopen(credential_request, timeout=5)
            except HTTPError as e:
                print("get token request failed: {}".format(e.reason))
                # raise RequestError("get token request failed: {}".format(e.reason))
            except URLError as e:
                print("get token connection failed: {}".format(e.reason))
            except socket.error as e:
                print("get token failed: {}".format(e))
                pass
                # raise RequestError("get token connection failed: {}".format(e.reason))
            response = credential_response.read().decode("utf-8")
            result = json.loads(response)
            access_token = result["access_token"]

            if allow_caching:
                # save the token for the duration it is valid for
                self.baidu_cached_access_token = access_token
                self.baidu_cached_access_token_expiry = start_time + (60 * 60 * 24 * 30)  # according to http://yuyin.baidu.com/docs/tts/135#%E8%8E%B7%E5%8F%96%20Access%20Token, the token expires in exactly 1 month

if __name__ == '__main__':
    rospy.init_node('tts')
    ChatController("ZxyGAMuX4h3NA0bl6YDCuuw1", "VGvaQVbBWHLueQdtOXGap11lNLdyFrwy", 0)
    rospy.spin()